package com.example.learningspringboot.mybatis.services.impl;

import com.example.learningspringboot.mybatis.mapper.MybatisMapper;
import com.example.learningspringboot.mybatis.pojo.User;
import com.example.learningspringboot.mybatis.services.MybatisService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Service
public class MybatisServiceImpl implements MybatisService {

    private final MybatisMapper mybatisMapper;

    @Autowired
    public MybatisServiceImpl(MybatisMapper mybatisMapper) {
        this.mybatisMapper = mybatisMapper;
    }

    /**
     * 这里使用了事务注解，指定了事务的传播行为和隔离级别
     * - Propagation.REQUIRED: 如果当前存在事务，则加入该事务；如果不存在，则创建一个新的事务。
     * - Isolation.REPEATABLE_READ: 保证在同一事务中多次读取同一数据时，数据不会发生变化。
     * 但是这里只是添加了事务注解，并没有实际的事务处理逻辑。
     * 在实际应用中，可能还需要处理异常、提交或回滚事务等操作。
     * 注意：在使用事务时，确保方法中的所有数据库操作都在同一个事务中执行，
     * 否则可能会导致数据不一致或事务无法正确提交。
     * 事务注解的使用需要在Spring Boot应用中开启事务管理，
     * 通常通过在主类上添加@EnableTransactionManagement注解来实现。
     * 事务的使用可以确保数据的一致性和完整性，特别是在涉及多个数据库操作时，
     * 可以通过事务来保证这些操作要么全部成功，要么全部失败，从而避免数据不一致的情况。
     * 事务的使用需要谨慎，尤其是在高并发场景下，
     * 需要考虑事务的隔离级别和锁的使用，以避免死锁或性能问题。
     * 还有事务失效的几种情况:
     * 1.方法被调用时没有事务存在，且方法没有被@Transactional注解标记。
     * 2.方法修饰不是public或protected，Spring AOP无法拦截。
     * 3.方法为静态方法，Spring AOP无法拦截静态方法的调用。
     * 4.方法调用自身(同一个类中方法互相调用)，Spring AOP无法拦截自身调用。
     * 5.方法调用其他类的非Spring管理的对象，Spring AOP无法拦截非Spring管理的对象。
     * 6.方法抛出异常，且异常类型不在@Transactional注解的rollbackFor或noRollbackFor指定的范围内。
     * 7.数据库不支持事务，或者数据库连接池配置不正确导致事务无法正常工作。
     * 等等，上面的1-6都是Spring代理类的限制导致的事务失效(我们要完全理解到Spring的bean的生命周期后就会更加深刻的理解)，
     * 第7条是数据库本身的限制。
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED, isolation= Isolation.REPEATABLE_READ, rollbackFor = Exception.class)
    public int createUser(User user) {
        return mybatisMapper.createUser(user);
    }

    @Override
    public int deleteUser(Integer id) {
        return mybatisMapper.deleteUser(id);
    }


    @Override
    public User findById(Integer id) {
        return mybatisMapper.findById(id);
    }

    @Override
    public List<User> findByIds(List<Integer> ids) {
        return mybatisMapper.findByIds(ids);
    }

    @Override
    public User findByNameAndCreateTime(String name, LocalDateTime createTime) {
        return mybatisMapper.findByNameAndCreateTime(name, createTime);
    }

    @Override
    public User findByCreateTime(LocalDateTime createTime) {
        return mybatisMapper.findByCreateTime(createTime);
    }
}
